package org.hairball.analysis;

import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.commons.EmptyVisitor;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.MethodNode;

import java.util.HashSet;
import java.util.Set;

public class SetterInjectionAnalyser implements RelationshipAnalyser {
    private static final ClassnameFilter classnameFilter = new ASMClassDescriptorFilter();

    public Set<Relationship> analyse(ClassNode classNode) {
        final Set<Relationship> classes = new HashSet<Relationship>();

        for (Object o : classNode.methods) {
            final MethodNode methodNode = ((MethodNode) o);
            if (methodNode.name.startsWith("set")) {

                MethodVisitor visitor = new EmptyVisitor() {
                    public void visitFieldInsn(int opcode, String definingClass, String fieldName, String classBeingAssigned) {
                        if (opcode == Opcodes.PUTFIELD) {

                            classes.add(createRel(definingClass, classBeingAssigned, methodNode));
                        }
                    }
                };
                methodNode.accept(visitor);
            }
        }

        return classes;
    }

    private Relationship createRel(String definingClass, String classBeingAssigned, MethodNode methodNode) {
        return new Relationship(classnameFilter.filter(definingClass), classnameFilter.filter(classBeingAssigned), methodNode.name);
    }
}
